package main

import (
	"fmt"
	"time"
)

/**go并发
goroutine 是轻量级线程，goroutine 的调度是由 Golang 运行时进行管理的。
goroutine 语法格式：
go 函数名( 参数列表 )
*/

func say(s string) {
	for i := 0; i < 5; i++ {
		time.Sleep(100 * time.Millisecond)
		fmt.Println(s)
	}
}

/*
*
执行以上代码，你会看到输出的 hello 和 world 是没有固定先后顺序。因为它们是两个 goroutine 在执行：
*/
func main17() {
	//go say("go")
	//say("hello")

	//s := []int{1, 2, 3, 4, 5, 6}
	//c := make(chan int)
	//go sum(s[:len(s)/2], c) //6
	//go sum(s[len(s)/2:], c) //15
	//x, y = <-c, <-c         // <- 从通道c中接收
	//fmt.Println(x, y, x+y)

	// 因为 ch 是带缓冲的通道，我们可以同时发送两个数据
	// 而不用立刻需要去同步读取数据
	//ch := make(chan int, 2)
	//ch <- 1
	//ch <- 2
	//fmt.Println(<-ch)
	//fmt.Println(<-ch)

	// range 函数遍历每个从通道接收到的数据，因为 c 在发送完 10 个
	// 数据之后就关闭了通道，所以这里我们 range 函数在接收到 10 个数据
	// 之后就结束了。如果上面的 c 通道不关闭，那么 range 函数就不
	// 会结束，从而在接收第 11 个数据的时候就阻塞了。
	c2 := make(chan int, 10)
	go closeChannel(cap(c2), c2)
	for i := range c2 {
		fmt.Println(i)
	}
}

/**
通道（channel）
通道（channel）是用来传递数据的一个数据结构。
声明一个通道很简单，我们使用chan关键字即可，通道在使用前必须先创建：
ch := make(chan int)
*/

func sum(s []int, c chan int) {
	sum := 0
	for _, v := range s {
		sum += v
	}
	c <- sum //把sum 发送到通道c

}

/**
Go 遍历通道与关闭通道
如果通道接收不到数据后 ok 就为 false，这时通道就可以使用 close() 函数来关闭。
*/

func closeChannel(n int, c chan int) {
	x, y := 0, 1
	for i := 0; i < n; i++ {
		c <- x
		x, y = y, x+y
	}
	close(c)
}
